package org.example.classtopia.Service.Impl;

import org.example.classtopia.Mapper.CourseMapper;
import org.example.classtopia.Model.Entity.UserMessage;
import org.example.classtopia.Model.dto.CourseCreateDTO;
import org.example.classtopia.Model.dto.CourseUpdateDTO;
import org.example.classtopia.Model.dto.CourseQueryDTO;
import org.example.classtopia.Model.Entity.Course;
import org.example.classtopia.Model.vo.CourseVO;
import org.example.classtopia.Service.CourseService;
import org.example.classtopia.Utils.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class CourseServiceImpl implements CourseService {
    private static final Logger logger = LoggerFactory.getLogger(CourseServiceImpl.class);

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private UserMessageService userMessageService;


    // 新增私有方法，校验HH:mm格式
    private boolean isValidTimeFormat(String timeStr) {
        try {
            LocalTime.parse(timeStr);  // 默认只要字符串符合ISO_LOCAL_TIME格式即可，"HH:mm" 也支持
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private boolean checkTimeConflict(Course course) {
        Long excludeId = course.getId(); // null表示新增，非null表示更新排除自己
        int count = courseMapper.countConflicts(
                course.getUserId(),
                course.getSemester(),
                course.getDayOfWeek(),
                course.getStartWeek(),
                course.getEndWeek(),
                course.getStartTime(),
                course.getEndTime(),
                excludeId);
        return count > 0;
    }


    @Override
    public Course createCourse(CourseCreateDTO courseCreateDTO) {

        // 校验时间格式
        if (!isValidTimeFormat(courseCreateDTO.getStartTime()) || !isValidTimeFormat(courseCreateDTO.getEndTime())) {
            // 这里可以抛异常，也可以直接返回null表示失败
            throw new IllegalArgumentException("开始时间或结束时间格式错误，必须为HH:mm");
        }

        // 业务规则校验示例，需自行根据eventType完善
        String eventType = courseCreateDTO.getEventType();
        if ("course".equals(eventType)) {
            if (courseCreateDTO.getTeacher() == null || courseCreateDTO.getTeacher().trim().isEmpty()) {
                throw new IllegalArgumentException("课程必须填写教师姓名");
            }
            if (courseCreateDTO.getDescription() != null && !courseCreateDTO.getDescription().trim().isEmpty()) {
                throw new IllegalArgumentException("课程不允许填写描述字段");
            }
        } else if ("schedule".equals(eventType)) {
            if (courseCreateDTO.getDescription() == null || courseCreateDTO.getDescription().trim().isEmpty()) {
                throw new IllegalArgumentException("日程必须填写描述");
            }
            if (courseCreateDTO.getTeacher() != null && !courseCreateDTO.getTeacher().trim().isEmpty()) {
                throw new IllegalArgumentException("日程不允许填写教师姓名");
            }
        } else {
            throw new IllegalArgumentException("事件类型非法");
        }



        Course course = new Course();
        BeanUtils.copyProperties(courseCreateDTO, course);

        if (checkTimeConflict(course)) {
            throw new IllegalArgumentException("时间冲突：已有课程或日程在该时间段");
        }

        // 针对日程（schedule）事件，提醒属性默认未提醒
        if ("schedule".equals(course.getEventType())) {
            course.setIsReminded(0);
        }

        course.setStatus(1);
        // 初始化默认状态：1 = 正常

        LocalDateTime now = LocalDateTime.now();
        course.setCreatedAt(now);
        course.setUpdatedAt(now);

        // TODO: 在这里调用冲突检测方法，检测是否冲突，若冲突则抛异常或返回null

        int rows = courseMapper.insertCourse(course);
        if (rows > 0) {
            // 确保从数据库重新查一遍course，包括数据库自动生成的字段
            Course savedCourse = courseMapper.selectCourseById(course.getId());
            return savedCourse; // 返回完整对象
        }
        return null;
    }

    @Override
    public CourseVO getCourseById(Long id) {
        Course course = courseMapper.selectCourseById(id);
        if (course == null) return null;

        CourseVO vo = new CourseVO();
        BeanUtils.copyProperties(course, vo);
        return vo;
    }

    @Override
    public List<CourseVO> getCoursesByUserAndWeek(CourseQueryDTO queryDTO) {

        List<Course> courseList = courseMapper.selectCoursesByUserAndWeek(
                queryDTO.getUserId(),
                queryDTO.getSemester(),
                queryDTO.getWeek());

        return courseList.stream()
                .map(course -> {
                    CourseVO vo = new CourseVO();
                    BeanUtils.copyProperties(course, vo);
                    return vo;
                }).collect(Collectors.toList());
    }

    @Override
    public boolean updateCourse(CourseUpdateDTO courseUpdateDTO) {
        Course old = courseMapper.selectCourseById(courseUpdateDTO.getId());
        if (old == null) return false;

        // 校验时间格式（如果传了时间，需要校验）
        if (courseUpdateDTO.getStartTime() != null && !isValidTimeFormat(courseUpdateDTO.getStartTime())) {
            throw new IllegalArgumentException("开始时间格式错误，必须为HH:mm");
        }
        if (courseUpdateDTO.getEndTime() != null && !isValidTimeFormat(courseUpdateDTO.getEndTime())) {
            throw new IllegalArgumentException("结束时间格式错误，必须为HH:mm");
        }

        Course course = new Course();
        course.setId(old.getId());
        course.setStatus(1);
        // 初始化默认状态：1 = 正常
        // 只更新有传入的字段，否则保持原值
        course.setUserId(courseUpdateDTO.getUserId() != null ? courseUpdateDTO.getUserId() : old.getUserId());
        course.setEventType(courseUpdateDTO.getEventType() != null ? courseUpdateDTO.getEventType() : old.getEventType());
        course.setName(courseUpdateDTO.getName() != null ? courseUpdateDTO.getName() : old.getName());
        course.setTeacher(courseUpdateDTO.getTeacher() != null ? courseUpdateDTO.getTeacher() : old.getTeacher());
        course.setDescription(courseUpdateDTO.getDescription() != null ? courseUpdateDTO.getDescription() : old.getDescription());
        course.setLocation(courseUpdateDTO.getLocation() != null ? courseUpdateDTO.getLocation() : old.getLocation());
        course.setDayOfWeek(courseUpdateDTO.getDayOfWeek() != null ? courseUpdateDTO.getDayOfWeek() : old.getDayOfWeek());
        course.setStartTime(courseUpdateDTO.getStartTime() != null ? courseUpdateDTO.getStartTime() : old.getStartTime());
        course.setEndTime(courseUpdateDTO.getEndTime() != null ? courseUpdateDTO.getEndTime() : old.getEndTime());
        course.setStartWeek(courseUpdateDTO.getStartWeek() != null ? courseUpdateDTO.getStartWeek() : old.getStartWeek());
        course.setEndWeek(courseUpdateDTO.getEndWeek() != null ? courseUpdateDTO.getEndWeek() : old.getEndWeek());
        course.setSemester(courseUpdateDTO.getSemester() != null ? courseUpdateDTO.getSemester() : old.getSemester());
        course.setColor(courseUpdateDTO.getColor() != null ? courseUpdateDTO.getColor() : old.getColor());

        course.setUpdatedAt(LocalDateTime.now());

        // 如果eventType是schedule且之前未提醒，更新时保持未提醒状态（不自动重置）
        if ("schedule".equals(course.getEventType()) && old.getIsReminded() != null) {
            course.setIsReminded(old.getIsReminded());
        }

        // TODO: 在这里调用冲突检测，防止时间冲突
        if (checkTimeConflict(course)) {
            throw new IllegalArgumentException("时间冲突：已有课程或日程在该时间段");
        }

        int rows = courseMapper.updateCourse(course);
        return rows > 0;
    }

    @Override
    public boolean deleteCourseById(Long id) {
        int rows = courseMapper.deleteCourseById(id);
        return rows > 0;
    }

    @Override
    public void sendTodayScheduleReminders(Long userId, String semester, int currentWeek, int currentDayOfWeek) {
        LocalTime now = LocalTime.now();
        LocalTime plus10 = now.plusMinutes(10);

        logger.info("检查用户:{}，时间window=[{},{}]，学期:{}，当前周:{}，星期:{}",
                userId, now, plus10, semester, currentWeek, currentDayOfWeek);

        List<Course> schedules = courseMapper.selectSchedulesStartingToday(
                userId,
                semester,
                currentWeek,
                currentDayOfWeek,
                now,
                plus10
        );

        LocalDate today = LocalDate.now();

        if (schedules.isEmpty()) {
            logger.info("用户{}当前时间段无日程提醒", userId);
            return;
        }

        for (Course schedule : schedules) {
            logger.debug("处理日程ID: {}, 名称: {}, 起止周: {}-{}, 星期: {}, 事件日: {}",
                    schedule.getId(), schedule.getName(), schedule.getStartWeek(), schedule.getEndWeek(),
                    schedule.getDayOfWeek(), schedule.getSemester());

            // 判断当前周是否在课程起止周内
            if (currentWeek < schedule.getStartWeek() || currentWeek > schedule.getEndWeek()) {
                logger.debug("跳过日程ID:{}，原因：当前周{}不在起止周范围{}-{}", schedule.getId(), currentWeek,
                        schedule.getStartWeek(), schedule.getEndWeek());
                continue; // 超出周次范围，跳过
            }

            // 判断星期几是否匹配
            if (schedule.getDayOfWeek() != currentDayOfWeek) {
                logger.debug("跳过日程ID:{}，原因：星期{}与当前星期{}不符", schedule.getId(), schedule.getDayOfWeek(), currentDayOfWeek);
                continue;
            }

            // 判断学期是否匹配
            //if (!schedule.getSemester().equals(todaySemester)) {
            //    continue;
            //}

            // 计算本周对应的实际日期
            LocalDate eventDate = DateUtils.calculateEventDate(schedule.getSemester(), currentWeek, schedule.getDayOfWeek());
            logger.debug("日程ID:{}对应的事件日期是{}", schedule.getId(), eventDate);
            // 只提醒当天
            if (!eventDate.equals(LocalDate.now())) {
                continue;
            }


            UserMessage msg = new UserMessage();
            msg.setUserId(schedule.getUserId());
            msg.setMessageType("system");
            msg.setContent("您的日程《" + schedule.getName() + "》将在10分钟内开始，请注意安排。");
            msg.setIsRead(0);
            msg.setTime(LocalDateTime.now());

            userMessageService.saveMessage(msg);

            // 这里标记为已提醒
            courseMapper.updateIsReminded(schedule.getId(), 1);
        }
    }

    public void markScheduleAsReminded(Long scheduleId) {
        courseMapper.updateIsReminded(scheduleId, 1);
    }

    @Override
    public Course createCourse(Course course) {
        // 业务校验参考你已有createCourse逻辑，转换为重载
        // 这里直接调用mapper插入
        int rows = courseMapper.insertCourse(course);
        if (rows > 0) {
            return courseMapper.selectCourseById(course.getId());
        }
        return null;
    }

    @Override
    public List<Course> findConflicts(Long userId, Integer fromWeek, Integer toWeek, Integer dayOfWeek, String startTime, String endTime) {
        return courseMapper.selectConflicts(userId, fromWeek, toWeek, dayOfWeek, startTime, endTime);
    }


}

